﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace Motar.ServiceModel
{
    
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TChannel"></typeparam>
    public class ClientFacade<TChannel> : ClientBase<TChannel>, IClientFacade<TChannel> where TChannel : class
    {

        /// <summary>
        /// 
        /// </summary>
        public ClientFacade() :
            base()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        public ClientFacade(InstanceContext callbackInstance) :
            base(callbackInstance)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="endpoint"></param>
        public ClientFacade(ServiceEndpoint endpoint) :
            base(endpoint)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="endpointConfigurationName"></param>
        public ClientFacade(string endpointConfigurationName) :
            base(endpointConfigurationName)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="binding"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(Binding binding, EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        /// <param name="endpoint"></param>
        public ClientFacade(InstanceContext callbackInstance, ServiceEndpoint endpoint) :
            base(callbackInstance, endpoint)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        /// <param name="endpointConfigurationName"></param>
        public ClientFacade(InstanceContext callbackInstance, string endpointConfigurationName) :
            base(callbackInstance, endpointConfigurationName)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="endpointConfigurationName"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(string endpointConfigurationName, EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="endpointConfigurationName"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        /// <param name="binding"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress) :
            base(callbackInstance, binding, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        /// <param name="endpointConfigurationName"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress) :
            base(callbackInstance, endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callbackInstance"></param>
        /// <param name="endpointConfigurationName"></param>
        /// <param name="remoteAddress"></param>
        public ClientFacade(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress) :
            base(callbackInstance, endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        public virtual void Execute(Action<TChannel> action)
        {
            action.Invoke(Channel);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        public virtual TResult Execute<TResult>(Func<TChannel, TResult> action)
        {
            return action.Invoke(Channel);
        }

        /// <summary>
        /// 
        /// </summary>
        void IDisposable.Dispose()
        {
            try
            {
                Close();
            }
            catch (CommunicationException)
            {
                Abort();
            }
            catch (TimeoutException)
            {
                Abort();
            }
            catch
            {
                Abort();

                throw;
            }
        }
    }
}
